package com.hyt.it.ogt.ykcj.service.grade.impl;

import cn.hutool.core.util.IdcardUtil;
import com.hyt.it.ogt.ykcj.common.constant.Constants;
import com.hyt.it.ogt.ykcj.common.core.domain.entity.SysUser;
import com.hyt.it.ogt.ykcj.common.enums.BizErrorCode;
import com.hyt.it.ogt.ykcj.common.exception.CustomException;
import com.hyt.it.ogt.ykcj.common.utils.DateUtils;
import com.hyt.it.ogt.ykcj.common.utils.IdUtils;
import com.hyt.it.ogt.ykcj.common.utils.SecurityUtils;
import com.hyt.it.ogt.ykcj.domain.exam.ExamPostInfo;
import com.hyt.it.ogt.ykcj.domain.exam.ExamStemInfo;
import com.hyt.it.ogt.ykcj.domain.exam.ExamSubjectInfo;
import com.hyt.it.ogt.ykcj.domain.grade.ServantExamineeInfo;
import com.hyt.it.ogt.ykcj.domain.grade.ServantExamineeSubjectGrade;
import com.hyt.it.ogt.ykcj.domain.vo.ServantExamineeGradeImportVo;
import com.hyt.it.ogt.ykcj.domain.vo.ServantExamineeInfoVo;
import com.hyt.it.ogt.ykcj.domain.vo.ServantExamineeSubjectGradeVo;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamPostInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamStemInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamSubjectInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.grade.ServantExamineeInfoMapper;
import com.hyt.it.ogt.ykcj.service.exam.IChangedExamInfoService;
import com.hyt.it.ogt.ykcj.service.grade.IServantExamineeGradeImportService;
import com.hyt.it.ogt.ykcj.service.grade.IServantExamineeInfoService;
import com.hyt.it.ogt.ykcj.service.system.ISysDictDataService;
import com.linuxense.javadbf.DBFReader;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.stream.Collectors;

/**
 * 公务员考生成绩导入Service业务层处理
 *
 * @author xiewx
 * @date 2021-11-02
 */
@Service
public class ServantExamineeGradeImportServiceImpl implements IServantExamineeGradeImportService {

    private static final Logger log = LoggerFactory.getLogger(ServantExamineeGradeImportServiceImpl.class);

    @Autowired
    private ExamSubjectInfoMapper examSubjectInfoMapper;

    @Autowired
    private ExamStemInfoMapper examStemInfoMapper;

    @Autowired
    private ServantExamineeInfoMapper servantExamineeInfoMapper;

    @Autowired
    private ISysDictDataService dictDataService;

    @Autowired
    private IServantExamineeInfoService servantExamineeInfoService;

    @Autowired
    private IChangedExamInfoService changedExamInfoService;

    @Autowired
    private ExamPostInfoMapper examPostInfoMapper;

    @Resource(name = "threadPoolTaskExecutor")
    protected ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Override
    public Object[] importtExcelFile(MultipartFile multipartFile, String examId, String subjectId) {
        log.info("导入成绩begin...文件类型为excel文件");
        long startTime = System.currentTimeMillis();
        FileInputStream fis = null;
        Workbook wb = null;
        try {
            String[] split = multipartFile.getOriginalFilename().split("\\.");  // . 特殊字符转义
            String originalFilename = multipartFile.getOriginalFilename();
            String[] fileName = originalFilename.split("\\.");
            File  file = File.createTempFile(fileName[0], fileName[1]);
            multipartFile.transferTo(file);
            file.deleteOnExit();
            fis = new FileInputStream(file);
            if ( "xls".equals(split[1].toLowerCase())) {
                wb = new HSSFWorkbook(fis);
            } else if ("xlsx".equals(split[1].toLowerCase())) {
                wb = new XSSFWorkbook(fis);
            }else {
                return  null;
            }
            // 开始解析
            Sheet sheet = wb.getSheetAt(0);     // 读取sheet 0
            int headRowIndex = sheet.getFirstRowNum();
            Row headRow = sheet.getRow(headRowIndex);
            if (null != headRow && sheet.getLastRowNum() > 0) {
                List<String> titles = new ArrayList<>(Arrays.asList(new String[] { "准考试号", "考生姓名", "性别", "身份证号", "报考职位编号", "报考部门编号" }));
                List<String> keys = new ArrayList<>(Arrays.asList(new String[] { "admissionNo", "name", "sex", "idcard", "bkzwdm", "bkdwdm" }));
                int firstCellIndex = headRow.getFirstCellNum(); // 开始列下标
                int lastCellIndex = headRow.getLastCellNum(); // 最后列下标
                if (StringUtils.isEmpty(subjectId)) { // 总成绩表
                    Map<String, Object> params = new HashMap<>();
                    params.put("examInfoId", examId);
                    List<ExamSubjectInfo> examSubjectInfoList = examSubjectInfoMapper.selectExamSubjectInfoListAllByParms(params); // 科目信息
                    if (!CollectionUtils.isEmpty(examSubjectInfoList)) {
                        if (lastCellIndex == (FIXED_FIELD_NUM + examSubjectInfoList.size())) {
                            for (ExamSubjectInfo subjectVo : examSubjectInfoList) {
                                titles.add(subjectVo.getExamSubjectName());
                                keys.add(subjectVo.getId());
                            }
                        } else {
                            throw new CustomException("导入文件列数与模板设定不一致，请检查!");
                        }
                    }
                } else { // 单科成绩表
                    Map<String, Object> params = new HashMap<>();
                    params.put("id", subjectId);
                    List<ExamSubjectInfo> examSubjectInfoList = examSubjectInfoMapper.selectExamSubjectInfoListAllByParms(params); // 科目信息
                    ExamStemInfo examStemInfo = new ExamStemInfo();
                    examStemInfo.setSubjectId(subjectId);
                    params = new HashMap<>();
                    params.put("orderBy", "sort");
                    examStemInfo.setParams(params);
                    List<ExamStemInfo> examStemInfoList = examStemInfoMapper.selectExamStemInfoList(examStemInfo); // 题干信息
                    if (!CollectionUtils.isEmpty(examStemInfoList)) {
                        if (lastCellIndex == (FIXED_FIELD_NUM + 1 + examStemInfoList.size())) { // 针对单科成绩表固定字段数需加一
                            titles.add("考试科目(" + examSubjectInfoList.get(0).getExamSubjectName() + ")");
                            keys.add(subjectId);
                            for (ExamStemInfo stemVo : examStemInfoList) {
                                titles.add(stemVo.getName());
                                keys.add(stemVo.getId());
                            }
                        } else {
                            throw new CustomException("导入文件列数与模板设定不一致，请检查!");
                        }
                    }
                }
                for (int cIndex = firstCellIndex; cIndex < lastCellIndex; cIndex++) {   //遍历列
                    Cell cell = headRow.getCell(cIndex);
                    if (cell != null) {
                        if (!cell.toString().equals(titles.get(cIndex))) {
                            throw new CustomException("导入文件第" + (cIndex+1) + "列【" + cell.toString() + "】的列名或循序与模板设定【" + titles.get(cIndex) + "】的列名不一致，请检查!");
                        }
                    }
                }
                return readExcelFile(sheet, keys, examId, subjectId);
            } else {
                throw new CustomException("导入文件无数据");
            }
        } catch (Exception e) {
            log.error("导入成绩出现异常：",e);
            throw new CustomException("导入成绩出现异常：" + e.getMessage());
        } finally {
            try {
                if (null != fis) {
                    fis.close();
                    log.info("文件流关闭成功");
                }
                if(null != wb){
                    wb.close();
                }
            } catch (Exception e) {
                log.info("文件流关闭失败！:{}",e);

            }
            long endTime = System.currentTimeMillis();
            log.info("导入成绩结束,共耗时{}秒",(endTime-startTime)/1000);
        }
    }

    /**
     * 读取Excel文件数据
     * @param sheet
     * @param keys 导入文件列标识
     * @param examId 考试ID
     * @param subjectId 科目ID
     * @return
     * @throws Exception
     */
    private Object[] readExcelFile(Sheet sheet, List<String> keys, String examId, String subjectId) throws Exception{
        List<ServantExamineeGradeImportVo> list = new ArrayList<>(); // 成功数据
        List<ServantExamineeGradeImportVo> errorlist = new ArrayList<>(); // 存放错误信息
        boolean flag = true; // 数据校验状态（false为存在错误）

        Map<String, ServantExamineeInfoVo> existingExamineeGradeMap = getExistingExamineeGradeMap(examId); // 已存在的考生列表
        Map<String, String> zwdmMap = getExamPostDmMap(examId); // 职位代码列表

        // 读取数据
        Map<String, Object> importExamineeGradeMap;
        int firstRowIndex = sheet.getFirstRowNum() + 1; // 第一行是列名，所以不读
        int lastRowIndex = sheet.getLastRowNum();
        for (int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) { // 遍历行
            Row row = sheet.getRow(rIndex);
            if (row != null) {
                importExamineeGradeMap = new HashMap<>();
                for (int cIndex = 0; cIndex < keys.size(); cIndex++) { // 遍历列
                    importExamineeGradeMap.put(keys.get(cIndex), row.getCell(cIndex));
                }
                ServantExamineeGradeImportVo examineeGradeVo = new ServantExamineeGradeImportVo();
                Map<String, String> sexDataMap = dictDataService.selectDictDataMap("sys_user_sex", "V");
                setExamineeGrade(examineeGradeVo, keys, importExamineeGradeMap, existingExamineeGradeMap, zwdmMap, sexDataMap, examId, subjectId, rIndex + 1);
                if (StringUtils.isNotEmpty(examineeGradeVo.getErrorMsg())) {
                    flag = false;
                    errorlist.add(examineeGradeVo);
                    continue;
                }
                list.add(examineeGradeVo);
            } else {
                throw new CustomException("导入文件无数据");
            }
        }

        // flag为false则返回errorlist
        if (!flag) {
            return new Object[]{flag, errorlist};
        }

        // list不为空则执行插入
        if (!CollectionUtils.isEmpty(list)) {
            batchInsertGrade(list);
            // 插入需要变更的考试信息
            changedExamInfoService.addChangedExamInfo(examId);
        }
        return new Object[]{flag, list.size()};
    }

    @Override
    public Object[] importtDbfFile(MultipartFile multipartFile, String examId, String subjectId) {
        log.info("导入成绩begin...文件类型为excel文件");
        long startTime = System.currentTimeMillis();
        InputStream is = null;
        try {
            // 读取文件的输入流
            is = multipartFile.getInputStream();
            // 根据输入流初始化一个DBFReader实例，用来读取DBF文件信息
            DBFReader reader = new DBFReader(is);
            // 解决乱码
            reader.setCharactersetName("GBK");
            // 总条数
            int recordCount = reader.getRecordCount();
            if (recordCount == 0) {
                throw new CustomException("导入文件无数据");
            }

            // 调用DBFReader对实例方法得到path文件中字段的个数
            int fieldCount = reader.getFieldCount(); // 获取字段数量
            List<String> titles = new ArrayList<>(Arrays.asList(new String[] { "准考试号", "考生姓名", "性别", "身份证号", "报考职位编号", "报考部门编号" }));
            List<String> keys = new ArrayList<>(Arrays.asList(new String[] { "admissionNo", "name", "sex", "idcard", "bkzwdm", "bkdwdm" }));
            if (StringUtils.isEmpty(subjectId)) { // 总成绩表
                Map<String, Object> params = new HashMap<>();
                params.put("examInfoId", examId);
                List<ExamSubjectInfo> examSubjectInfoList = examSubjectInfoMapper.selectExamSubjectInfoListAllByParms(params); // 科目信息
                if (!CollectionUtils.isEmpty(examSubjectInfoList)) {
                    if (fieldCount == (FIXED_FIELD_NUM + examSubjectInfoList.size())) {
                        for (ExamSubjectInfo subjectVo : examSubjectInfoList) {
                            titles.add(subjectVo.getExamSubjectName());
                            keys.add(subjectVo.getId());
                        }
                    } else {
                        throw new CustomException("导入文件列数与模板设定不一致，请检查!");
                    }
                }
            } else { // 单科成绩表
                ExamStemInfo examStemInfo = new ExamStemInfo();
                examStemInfo.setSubjectId(subjectId);
                Map<String, Object> params = new HashMap<>();
                params.put("orderBy", "sort");
                examStemInfo.setParams(params);
                List<ExamStemInfo> examStemInfoList = examStemInfoMapper.selectExamStemInfoList(examStemInfo); // 题干信息
                if (!CollectionUtils.isEmpty(examStemInfoList)) {
                    if (fieldCount == (FIXED_FIELD_NUM + 1 + examStemInfoList.size())) { // 针对单科成绩表固定字段数需加一
                        titles.add("考试科目");
                        keys.add(subjectId);
                        for (ExamStemInfo stemVo : examStemInfoList) {
                            titles.add(stemVo.getName());
                            keys.add(stemVo.getId());
                        }
                    } else {
                        throw new CustomException("导入文件列数与模板设定不一致，请检查!");
                    }
                }
            }
            for (int i = 0; i < fieldCount; i++) {
                String fieldName = reader.getField(i).getName();
                if (fieldName != null) {
                    if (!fieldName.equals(titles.get(i))) {
                        throw new CustomException("导入文件第" + (i+1) + "列【" + fieldName + "】的列名或循序与模板设定【" + titles.get(i) + "】的列名不一致，请检查!");
                    }
                }
            }
            return readDbfFile(reader, keys, examId, subjectId);
        } catch (Exception e) {
            log.error("导入成绩出现异常：",e);
            throw new CustomException("导入成绩出现异常:{}" ,e);
        } finally {
            try {
                if(null != is){
                    is.close();
                    log.info("文件流关闭成功");
                }
            } catch (Exception e) {
                log.info("文件流关闭失败");
            }
            long endTime = System.currentTimeMillis();
            log.info("导入成绩结束,共耗时{}秒",(endTime-startTime)/1000);
        }
    }

    /**
     * 读取DBF文件数据
     * @param reader
     * @param keys 导入文件列标识
     * @param examId 考试ID
     * @param subjectId 科目ID
     * @return
     * @throws Exception
     */
    private Object[] readDbfFile(DBFReader reader, List<String> keys, String examId, String subjectId) throws Exception{
        List<ServantExamineeGradeImportVo> list = new ArrayList<>(); // 成功数据
        List<ServantExamineeGradeImportVo> errorlist = new ArrayList<>(); // 存放错误信息
        boolean flag = true; // 数据校验状态（false为存在错误）

        Map<String, ServantExamineeInfoVo> existingExamineeGradeMap = getExistingExamineeGradeMap(examId); // 已存在的考生列表
        Map<String, String> zwdmMap = getExamPostDmMap(examId); // 职位代码列表

        // 一条条取出path文件中记录
        Map<String, Object> importExamineeGradeMap;
        Object[] rValues;
        int rIndex = 0; // 记录行数
        while ((rValues = reader.nextRecord()) != null) {
            rIndex++;
            importExamineeGradeMap = new HashMap<>();
            for (int cIndex = 0; cIndex < keys.size(); cIndex++) { // 遍历列
                importExamineeGradeMap.put(keys.get(cIndex), rValues[cIndex]);
            }
            ServantExamineeGradeImportVo examineeGradeVo = new ServantExamineeGradeImportVo();
            Map<String, String> sexDataMap = dictDataService.selectDictDataMap("sys_user_sex", "V");
            setExamineeGrade(examineeGradeVo, keys, importExamineeGradeMap, existingExamineeGradeMap, zwdmMap, sexDataMap, examId, subjectId, rIndex);
            if (StringUtils.isNotEmpty(examineeGradeVo.getErrorMsg())) {
                flag = false;
                errorlist.add(examineeGradeVo);
                continue;
            }
            list.add(examineeGradeVo);
        }

        // flag为false则返回errorlist
        if (!flag) {
            return new Object[]{flag, errorlist};
        }

        // list不为空则执行插入
        if (!CollectionUtils.isEmpty(list)) {
            batchInsertGrade(list);
            // 插入需要变更的考试信息
            changedExamInfoService.addChangedExamInfo(examId);
        }
        return new Object[]{flag, list.size()};
    }

    /**
     * 获取已存在的考生列表
     * @param examId 考试ID
     * @return
     */
    private Map<String, ServantExamineeInfoVo> getExistingExamineeGradeMap(String examId) {
        List<ServantExamineeInfoVo> existingExamineeGradelist = servantExamineeInfoMapper.selectExistingExamineeGradeList(examId);
        if (!CollectionUtils.isEmpty(existingExamineeGradelist)) {
            return existingExamineeGradelist.stream().collect(Collectors.toMap(ServantExamineeInfoVo::getIdcard, ServantExamineeInfoVo -> ServantExamineeInfoVo));
        } else {
            return new HashMap<>();
        }
    }

    /**
     * 获取职位代码列表
     * @param examId 考试ID
     * @return
     */
    private Map<String, String> getExamPostDmMap(String examId) {
        ExamPostInfo examPostInfo = new ExamPostInfo();
        examPostInfo.setExamId(examId);
        List<ExamPostInfo> examPostInfoList = examPostInfoMapper.selectExamPostInfoList(examPostInfo);
        if (!CollectionUtils.isEmpty(examPostInfoList)) {
            return examPostInfoList.stream().collect(Collectors.toMap(ExamPostInfo::getZwdm, ExamPostInfo::getDwdm));
        } else {
            return new HashMap<>();
        }
    }

    /**
     * 设置考生成绩数据
     * @param examineeGradeVo
     * @param keys 导入文件列标识
     * @param importExamineeGradeMap 导入文件行数据
     * @param existingExamineeGradeMap 已存在的考生成绩集合
     * @param sexDictMap 性别字典
     * @param examId 考试ID
     * @param subjectId 科目ID
     * @param rowNum 行号
     * @return
     * @throws Exception
     */
    private void setExamineeGrade(ServantExamineeGradeImportVo examineeGradeVo, List<String> keys, Map<String, Object> importExamineeGradeMap, Map<String,ServantExamineeInfoVo> existingExamineeGradeMap, Map<String, String> zwdmMap, Map<String, String> sexDictMap, String examId, String subjectId, int rowNum) throws Exception {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        String examineeId = IdUtils.generateId();
        ServantExamineeInfo servantExamineeInfo = new ServantExamineeInfo();
        servantExamineeInfo.setId(examineeId);
        servantExamineeInfo.setExamId(examId);
        servantExamineeInfo.createInfo(SecurityUtils.getUsername());
        servantExamineeInfo.updateInfo(SecurityUtils.getUsername());
        List<ServantExamineeSubjectGrade> servantExamineeGradeList = new ArrayList<>();
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            if (i < FIXED_FIELD_NUM) {
                Field classField = ServantExamineeInfo.class.getDeclaredField(key);
                classField.setAccessible(true);
                setFieldValue(servantExamineeInfo, importExamineeGradeMap.get(key), classField);
            } else {
                ServantExamineeSubjectGrade grade = new ServantExamineeSubjectGrade();
                grade.setId(IdUtils.generateId());
                grade.setExamId(examId);
                grade.setExamineeId(examineeId);
                if (StringUtils.isEmpty(subjectId)) { // 总成绩
                    grade.setSubjectId(key);
                    grade.setStemId("");
                } else { // 单科成绩
                    if (i == FIXED_FIELD_NUM) { // 单科成绩 跳过 科目名称列
                        continue;
                    }
                    grade.setSubjectId(subjectId);
                    grade.setStemId(key);
                }
                Object score = importExamineeGradeMap.get(key);
                if (null != score) {
                    grade.setScore(new BigDecimal(score.toString()));
                }
                grade.setDeptId(sysUser.getDeptId());
                grade.createInfo(SecurityUtils.getUsername());
                grade.updateInfo(SecurityUtils.getUsername());
                servantExamineeGradeList.add(grade);
            }
        }
        servantExamineeInfo.setSex(sexDictMap.get(servantExamineeInfo.getSex()));
        // 单科成绩导入的总分处理
        if (StringUtils.isNotEmpty(subjectId)) { // 题型分数合并成单科总分
            ServantExamineeSubjectGrade grade = new ServantExamineeSubjectGrade();
            servantExamineeInfoService.getSubjectGrade(servantExamineeGradeList, grade);
            servantExamineeGradeList.add(grade);
        }
        examineeGradeVo.setServantExamineeInfo(servantExamineeInfo);
        examineeGradeVo.setServantExamineeGradeList(servantExamineeGradeList);
        // 校验身份证号
        if (!IdcardUtil.isValidCard(servantExamineeInfo.getIdcard())) {
            examineeGradeVo.setErrorMsg("身份证号码【" + servantExamineeInfo.getIdcard() + "】格式错误，请检查导入文件第" + rowNum + "行数据！");
            return;
        }
        // 校验职位代码
        String bkdwdm = zwdmMap.get(servantExamineeInfo.getBkzwdm());
        if (StringUtils.isNotEmpty(bkdwdm)) {
            servantExamineeInfo.setBkdwdm(bkdwdm);
        } else {
            examineeGradeVo.setErrorMsg("报考职位编号 " + servantExamineeInfo.getBkzwdm() + " 错误，请检查导入文件第\" + rowNum + \"行数据！");
            return;
        }
        // 通过身份证号获取性别
        if (Integer.parseInt(servantExamineeInfo.getIdcard().substring(16, 17)) % 2 == 0) {
            servantExamineeInfo.setSex(Constants.SEX_WOMAN);
        } else {
            servantExamineeInfo.setSex(Constants.SEX_MAN);
        }

        // 如果已存在考生成绩信息，则更新
        ServantExamineeInfoVo examineeInfoVoOld = existingExamineeGradeMap.get(servantExamineeInfo.getIdcard());
        if (null != examineeInfoVoOld) {
            String examineeIdOld = examineeInfoVoOld.getId();
            servantExamineeInfo.setId(examineeIdOld);
            servantExamineeInfo.setArchivedStatus("N");
            servantExamineeInfo.setCreateBy(null); // 更新不更新数据创建人
            servantExamineeInfo.setCreateTime(null); // 更新不更新数据创建时间
            List<ServantExamineeSubjectGradeVo> gradeVoListOld = existingExamineeGradeMap.get(servantExamineeInfo.getIdcard()).getGradeList();
            Map<String, ServantExamineeSubjectGradeVo> gradeVoMapOld = gradeVoListOld.stream().collect(Collectors.toMap(k -> k.getSubjectId() + k.getStemId(), ServantExamineeSubjectGradeVo -> ServantExamineeSubjectGradeVo));
            for (ServantExamineeSubjectGrade grade : servantExamineeGradeList) {
                grade.setExamineeId(examineeIdOld);
                ServantExamineeSubjectGradeVo gradeVoOld = gradeVoMapOld.get(grade.getSubjectId() + grade.getStemId());
                if (null != gradeVoOld) {
                    grade.setId(gradeVoOld.getId());
                    grade.setCreateBy(null); // 更新不更新数据创建人
                    grade.setCreateTime(null); // 更新不更新数据创建时间
                }
            }
        }
    }

    /**
     * 字段设置名称
     * @param obj 设置的对象
     * @param val 设置的字段值
     * @param classField 设置的字段
     * @throws Exception
     */
    private static void setFieldValue(Object obj, Object val, Field classField) throws Exception {
        if (val != null) {
            if (classField.getType() == Integer.class) {
                classField.set(obj, Integer.parseInt(val.toString()));
            } else if (classField.getType() == String.class) {
                String value = val.toString().trim();
                String arr[] = value.split("\\.");
                if (arr.length > 1) {
                    classField.set(obj, arr[0]);
                } else {
                    classField.set(obj, value);
                }
            } else if (classField.getType() == Long.class) {
                classField.set(obj, Long.parseLong(val.toString()));
            } else if (classField.getType() == BigDecimal.class) {
                classField.set(obj, new BigDecimal(val.toString()));
            }
        }
    }

    /**
     * 异步批量插入成绩
     * @param list
     */
    public void batchInsertGrade(List<ServantExamineeGradeImportVo> list) {
        int count = list.size() % BATCH_COUNT == 0 ? list.size() / BATCH_COUNT : list.size() / BATCH_COUNT + 1;
        // 循环创建线程
        CountDownLatch countDownLatch = new CountDownLatch(count);
        List<FutureTask<Boolean>> resultList = Lists.newArrayList();
        for (int i = 0; i < count; i++) {
            List<ServantExamineeGradeImportVo> gradeInfoVos = new ArrayList<>(BATCH_COUNT);
            if (i + 1 == count) {
                gradeInfoVos.addAll(list.subList(i * BATCH_COUNT, list.size()));
            } else {
                gradeInfoVos.addAll(list.subList(i * BATCH_COUNT, (i + 1) * BATCH_COUNT));
            }
            FutureTask<Boolean> future =  new FutureTask<>(new ImportGradeTask(gradeInfoVos, countDownLatch));
            threadPoolTaskExecutor.submit(future);
            //将任务执行结果存储到List中
            resultList.add(future);

        }
        try {
            countDownLatch.await();
            for (FutureTask<Boolean> futureTask : resultList) {
                if(!futureTask.get()){
                    throw new CustomException(BizErrorCode.GRADE_E0006);
                }
            }
            log.info("异步批量插入成绩任务完成" + DateUtils.localDateMillisToString(LocalDateTime.now()));
        } catch (InterruptedException e) {
            log.error(e.getCause().getMessage());
            Thread.currentThread().interrupt();
            throw new CustomException(BizErrorCode.GRADE_E0006);
        } catch (ExecutionException e) {
            // 看看失败原因
            log.error(e.getCause().getMessage());
            throw new CustomException(BizErrorCode.GRADE_E0006);
        }
    }

    /**
     * 异步插入成绩处理
     */
    public class ImportGradeTask  implements Callable<Boolean> {

        private List<ServantExamineeGradeImportVo> gradeInfoVos;

        private CountDownLatch countDownLatch;

        public ImportGradeTask(List<ServantExamineeGradeImportVo> gradeInfoVos,CountDownLatch countDownLatch) {
            this.gradeInfoVos = gradeInfoVos;
            this.countDownLatch = countDownLatch ;
        }

        @Override
        public Boolean call(){
            try {
                log.info("SaveData size: {}", gradeInfoVos.size());
                servantExamineeInfoService.insertBatchExamineeGrade(gradeInfoVos);
                return true;
            } finally {
                countDownLatch.countDown();
            }
        }
    }

}

